#include "include/video_codec.h"
namespace codec {

bool VideoCodec::init(AVCodecParameters* codec_params) {
  const char* hw_decoder_name = nullptr;
  switch (codec_params->codec_id) {
    case AV_CODEC_ID_H264:
      hw_decoder_name = "h264_mediacodec";
      break;
    case AV_CODEC_ID_HEVC:
      hw_decoder_name = "hevc_mediacodec";
      break;
    case AV_CODEC_ID_VP8:
      hw_decoder_name = "vp8_mediacodec";
      break;
    case AV_CODEC_ID_VP9:
      hw_decoder_name = "vp9_mediacodec";
      break;
    default:
      break;
  }
  // 先不用硬解
  // if (hw_decoder_name) {
  //   codec_ = avcodec_find_decoder_by_name(hw_decoder_name);
  // }

  // 回退到软件解码
  if (!codec_) {
    codec_ = avcodec_find_decoder(codec_params->codec_id);
  }

  if (!codec_) return false;

  codec_ctx_ = avcodec_alloc_context3(codec_);
  if (avcodec_parameters_to_context(codec_ctx_, codec_params) < 0) {
    return false;
  }

  // 初始化硬件设备
  if (hw_decoder_name &&
      av_hwdevice_ctx_create(&hw_device_ctx_, AV_HWDEVICE_TYPE_MEDIACODEC,
                             nullptr, 0, 0) >= 0) {
    codec_ctx_->hw_device_ctx = av_buffer_ref(hw_device_ctx_);
  }

  return (avcodec_open2(codec_ctx_, codec_, nullptr) >= 0);
}

void VideoCodec::close() {
  // 1. 释放编解码器上下文（自动解除硬件引用）
  if (codec_ctx_) {
    avcodec_free_context(&codec_ctx_);
    codec_ctx_ = nullptr;
  }

  // 2. 独立释放硬件设备上下文
  if (hw_device_ctx_) {
    av_buffer_unref(&hw_device_ctx_);
    hw_device_ctx_ = nullptr;
  }

  // 3. 重置编解码器指针
  codec_ = nullptr;
}

bool VideoCodec::sendPacket(AVPacket* packet) {
  // 检查解码器状态
  if (!codec_ctx_) {
    return false;
  }

  int ret = avcodec_send_packet(codec_ctx_, packet);

  // 处理不同返回状态
  switch (ret) {
    case 0:  // 成功发送数据包
      return true;

    case AVERROR(EAGAIN):
      // 输入缓冲区已满，需要先接收解码帧
      __android_log_print(ANDROID_LOG_DEBUG, "Decoder",
                          "Input buffer full, need to receive frames first");
      return false;

    case AVERROR_EOF:
      __android_log_print(ANDROID_LOG_WARN, "Decoder",
                          "Decoder has already been flushed");
      return false;

    case AVERROR(EINVAL):
      __android_log_print(ANDROID_LOG_ERROR, "Decoder",
                          "Invalid argument or decoder not opened");
      return false;

    case AVERROR(ENOMEM):
      __android_log_print(
          ANDROID_LOG_ERROR, "Decoder",
          "Failed to add packet to internal queue (out of memory)");
      return false;

    default:
      char errbuf[AV_ERROR_MAX_STRING_SIZE];
      av_strerror(ret, errbuf, sizeof(errbuf));
      __android_log_print(ANDROID_LOG_ERROR, "Decoder",
                          "Failed to send packet: %s (code %d)", errbuf, ret);
      return false;
  }
}
AVFrame* VideoCodec::receiveFrame() {
  AVFrame* frame = av_frame_alloc();
  if (avcodec_receive_frame(codec_ctx_, frame) == 0) {
    return frame;
  }
  av_frame_free(&frame);
  return nullptr;
}

}  // namespace codec